﻿
// **************************************************************************
//    Class Created by Mick Doherty (Dotnetrix) March 2010
//    http://dotnetrix.co.uk/
//
//    ...for GlassUI (an AeroGlass UI Library)
//    http://glassui.codeplex.com/
// **************************************************************************

using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace GlassUI
{
    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Renderer")]
    public class GlassToolStripRenderer : ToolStripRenderer
    {
        #region Private Instance Variables

        Rectangle[] baseSizeGripRectangles = new Rectangle[] { new Rectangle(8, 0, 2, 2), new Rectangle(8, 4, 2, 2), new Rectangle(8, 8, 2, 2), new Rectangle(4, 4, 2, 2), new Rectangle(4, 8, 2, 2), new Rectangle(0, 8, 2, 2) };

        #endregion

        #region Render Methods

        protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
        {
            RenderArrowInternal(e.Graphics, e.ArrowRectangle, e.Direction, Color.Black);
        }

        protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e)
        {
            base.OnRenderButtonBackground(e);
            bool isCheckedItem = e.Item is ToolStripButton ? ((ToolStripButton)e.Item).Checked : e.Item.Pressed;
            Rectangle rc = new Rectangle(Point.Empty, e.Item.Size);
            this.RenderButtonInternal(e.Graphics, e.ToolStrip, rc, e.Item.Selected, isCheckedItem,e.Item.Pressed);
        }

        protected override void OnRenderDropDownButtonBackground(ToolStripItemRenderEventArgs e)
        {
            base.OnRenderDropDownButtonBackground(e);
            this.OnRenderButtonBackground(e);
        }

        // Ripped from ToolStripProfessionalRenderer 
        protected override void OnRenderGrip(ToolStripGripRenderEventArgs e)
        {
            Graphics graphics = e.Graphics;
            Rectangle gripBounds = e.GripBounds;
            ToolStrip toolStrip = e.ToolStrip;
            bool flag = e.ToolStrip.RightToLeft == RightToLeft.Yes;
            int num = (toolStrip.Orientation == Orientation.Horizontal) ? gripBounds.Height : gripBounds.Width;
            int num2 = (toolStrip.Orientation == Orientation.Horizontal) ? gripBounds.Width : gripBounds.Height;
            int num3 = (num - 8) / 4;
            if (num3 > 0)
            {
                int num4 = (toolStrip is MenuStrip) ? 2 : 0;
                Rectangle[] rects = new Rectangle[num3];
                int y = 5 + num4;
                int x = num2 / 2;
                for (int i = 0; i < num3; i++)
                {
                    rects[i] = (toolStrip.Orientation == Orientation.Horizontal) ? new Rectangle(x, y, 2, 2) : new Rectangle(y, x, 2, 2);
                    y += 4;
                }
                int num8 = flag ? 1 : -1;
                if (flag)
                {
                    for (int k = 0; k < num3; k++)
                    {
                        rects[k].Offset(-num8, 0);
                    }
                }
                using (Brush brush = new SolidBrush(Color.FromArgb(128, Color.White)))
                {
                    graphics.FillRectangles(brush, rects);
                }
                for (int j = 0; j < num3; j++)
                {
                    rects[j].Offset(num8, -1);
                }
                using (Brush brush2 = new SolidBrush(Color.FromArgb(128, Color.Black)))
                {
                    graphics.FillRectangles(brush2, rects);
                }
            }
        }

        protected override void OnRenderImageMargin(ToolStripRenderEventArgs e)
        {
            using (Brush brush = new SolidBrush(Color.FromArgb(64, Color.Black)))
                e.Graphics.FillRectangle(brush, e.AffectedBounds);
        }

        protected override void OnRenderItemBackground(ToolStripItemRenderEventArgs e)
        {
            if (e.Item is ToolStripTab)
                this.OnRenderTabBackground(e);
            else
                base.OnRenderItemBackground(e);
        }

        protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
        {
            if (e.Image != null && e.Item.Image == null)
            {
                ToolStripMenuItem item = e.Item as ToolStripMenuItem;

                if (item != null)
                {
                    if (item.CheckState != CheckState.Unchecked)
                    {
                        Rectangle bounds = e.ImageRectangle;
                        using (Brush brush = new SolidBrush(e.Item.BackColor))
                            e.Graphics.FillRectangle(brush, bounds);

                        bounds.Inflate(-2, -2);

                        using (Brush brush = new SolidBrush(e.Item.ForeColor))
                        {
                            switch (item.CheckState)
                            {
                                case CheckState.Indeterminate:
                                    Rectangle r = new Rectangle(bounds.Left + bounds.Width / 2 - 3, bounds.Top + bounds.Height / 2 - 3, 6, 6);
                                    e.Graphics.FillEllipse(brush, r);
                                    break;
                                default:
                                    Point[] pt = new Point[]{
                                        new Point(bounds.Left, bounds.Top + bounds.Height/2),
                                        new Point(bounds.Left + bounds.Width/3, bounds.Top + bounds.Height),
                                        new Point(bounds.Left + bounds.Width, bounds.Top),
                                        new Point(bounds.Left+bounds.Width/3, bounds.Top + (int)(bounds.Height *0.7)),
                                        new Point(bounds.Left, bounds.Top + bounds.Height/2)};
                                    using (GraphicsPath p = new GraphicsPath())
                                    {
                                        p.AddLines(pt);
                                        p.CloseFigure();
                                        e.Graphics.FillPath(brush, p);
                                    }
                                    break;
                            }
                        }
                    }
                }
            }
        }

        protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e)
        {
            if (e.Image != null)
            {
                Image img = e.Item.Enabled ? e.Image : ToolStripRenderer.CreateDisabledImage(e.Image);
                e.Graphics.DrawImage(img, e.ImageRectangle);
            }
        }

        protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
        {
            Rectangle desiredBounds = e.TextRectangle;
            desiredBounds.Inflate(4, 0);
            Size glowSize = desiredBounds.Size;

            Size textSize = GlassUtilities.MeasureThemedText(e.Graphics, e.Text, e.TextFont, glowSize, e.TextFormat, 8);

            desiredBounds.Height = textSize.Height;

            switch (e.Item.TextImageRelation)
            {
                case TextImageRelation.TextAboveImage:
                    desiredBounds.Y = (e.Item.Bounds.Height - e.Item.Image.Height - desiredBounds.Height) / 2;
                    break;
                case TextImageRelation.ImageAboveText:
                    desiredBounds.Y = (e.Item.Bounds.Height + e.Item.Image.Height - desiredBounds.Height) / 2;
                    break;
                default:
                    desiredBounds.Y = (e.Item.Bounds.Height - desiredBounds.Height) / 2;
                    break;
            }

            Color textColor = !e.Item.Enabled ? SystemColors.GrayText : e.Item is ToolStripMenuItem ? e.Item.ForeColor : e.TextColor;
            
            GlassUtilities.DrawThemedText(e.Graphics, e.Text, e.TextFont, desiredBounds, textColor, e.TextFormat, 8, e.TextDirection);
        }

        protected override void OnRenderLabelBackground(ToolStripItemRenderEventArgs e)
        {
            base.OnRenderLabelBackground(e);
        }

        [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
        protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;

            ToolStrip topStrip = this.TopMostToolStrip(e.ToolStrip);
            Control sourceControl = topStrip is ContextMenuStrip ? ((ContextMenuStrip)topStrip).SourceControl : topStrip;
            GlassForm form = sourceControl == null ? null : sourceControl.FindForm() as GlassForm;

            Color glowColor = SystemColors.Highlight;

            if (form != null)
            {
                glowColor = form.GetGlowColor(topStrip);
                if (glowColor.IsEmpty)
                    glowColor = form.GlowColor;
            }

            if (e.Item.Selected || e.Item.Pressed && !GlassToolStripRenderer.DesignMode(e.ToolStrip))
            {
                Rectangle rc = e.ToolStrip.IsDropDown ?
                    e.Item.ContentRectangle :
                    new Rectangle(Point.Empty, e.Item.Size);

                if (!e.ToolStrip.IsDropDown)
                    rc.Inflate(0, -1);

                Color glass = glowColor;

                using (GraphicsPath path = GlassUtilities.RoundedRectangle(rc, 4))
                {
                    int gradientAngle = e.ToolStrip.Orientation == Orientation.Horizontal ? 90 : 0;
                    using (Brush brush = new LinearGradientBrush(rc, Color.FromArgb(128, Color.White), glass, gradientAngle))
                        e.Graphics.FillPath(brush, path);

                    using (Pen pen = new Pen(Color.FromArgb(Math.Max(192, (int)glass.A), glass)))
                    {
                        e.Graphics.DrawPath(pen, path);

                        rc.Inflate(-1, -1);
                        path.Reset();
                        path.AddPath(GlassUtilities.RoundedRectangle(rc, 3), false);
                        pen.Color = Color.FromArgb(192, Color.White);
                        e.Graphics.DrawPath(pen, path);
                    }
                }

            }
        }

        protected override void OnRenderOverflowButtonBackground(ToolStripItemRenderEventArgs e)
        {
            base.OnRenderOverflowButtonBackground(e);
            Graphics g = e.Graphics;

            this.OnRenderButtonBackground(e);

            bool itemIsHorizontal = e.ToolStrip.Orientation == Orientation.Horizontal;
            Rectangle arrowBounds = new Rectangle(Point.Empty, e.Item.Size);
            arrowBounds.X = arrowBounds.Width / 2 - 5;
            arrowBounds.Width = 10;
            arrowBounds.Y = arrowBounds.Bottom - 14;
            arrowBounds.Height = 10;

            ArrowDirection direction = itemIsHorizontal ? ArrowDirection.Down : ArrowDirection.Right;

            e.Graphics.CompositingMode = CompositingMode.SourceOver;
            
            RenderArrowInternal(g, arrowBounds, direction, Color.Black);

            using (Pen pen = new Pen(Color.Black))
            {
                if (itemIsHorizontal)
                {
                    g.DrawLine(pen, arrowBounds.X + 2, arrowBounds.Y + 1, arrowBounds.Right - 2, arrowBounds.Y + 1);
                }
                else
                {
                    g.DrawLine(pen, arrowBounds.X, arrowBounds.Y + 2, arrowBounds.X, arrowBounds.Bottom - 2);
                }
            }
        }

        // Ripped from ToolStripProfessionalRenderer 
        protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
        {
            Color separatorDark = Color.FromArgb(128, Color.Black);
            Color separatorLight = Color.FromArgb(128, Color.White);
            Pen darkPen = new Pen(separatorDark);
            Pen lightPen = new Pen(separatorLight);

            Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);

            bool flag = true;
            bool flag2 = true;
            bool flag3 = e.Item is ToolStripSeparator;
            bool flag4 = false;
            if (flag3)
            {
                if (e.Vertical)
                {
                    if (!e.Item.IsOnDropDown)
                    {
                        bounds.Y += 3;
                        bounds.Height = Math.Max(0, bounds.Height - 6);
                    }
                }
                else
                {
                    ToolStripDropDownMenu currentParent = e.Item.GetCurrentParent() as ToolStripDropDownMenu;
                    if (currentParent != null)
                    {
                        if (currentParent.RightToLeft == RightToLeft.No)
                        {
                            bounds.X += currentParent.Padding.Left - 2;
                            bounds.Width = currentParent.Width - bounds.X;
                        }
                        else
                        {
                            bounds.X += 2;
                            bounds.Width = (currentParent.Width - bounds.X) - currentParent.Padding.Right;
                        }
                    }
                    else
                    {
                        flag4 = true;
                    }
                }
            }
            try
            {
                if (e.Vertical)
                {
                    if (bounds.Height >= 4)
                    {
                        bounds.Inflate(0, -2);
                    }
                    bool flag5 = e.Item.RightToLeft == RightToLeft.Yes;
                    Pen pen3 = flag5 ? lightPen : darkPen;
                    Pen pen4 = flag5 ? darkPen : lightPen;
                    int num = bounds.Width / 2;
                    e.Graphics.DrawLine(pen3, num, bounds.Top, num, bounds.Bottom - 1);
                    num++;
                    e.Graphics.DrawLine(pen4, num, bounds.Top + 1, num, bounds.Bottom);
                }
                else
                {
                    if (flag4 && (bounds.Width >= 4))
                    {
                        bounds.Inflate(-2, 0);
                    }
                    int num2 = bounds.Height / 2;
                    e.Graphics.DrawLine(darkPen, bounds.Left, num2, bounds.Right - 1, num2);
                    if (!flag3 || flag4)
                    {
                        num2++;
                        e.Graphics.DrawLine(lightPen, bounds.Left + 1, num2, bounds.Right - 1, num2);
                    }
                }
            }
            finally
            {
                if (flag && (darkPen != null))
                {
                    darkPen.Dispose();
                }
                if (flag2 && (lightPen != null))
                {
                    lightPen.Dispose();
                }
            }
        }

        protected override void OnRenderSplitButtonBackground(ToolStripItemRenderEventArgs e)
        {
            base.OnRenderSplitButtonBackground(e);

            ToolStripSplitButton splitButton = e.Item as ToolStripSplitButton;
            Rectangle buttonBounds = new Rectangle(Point.Empty, splitButton.ButtonBounds.Size);
            Rectangle arrowBounds = Rectangle.FromLTRB(buttonBounds.Right, buttonBounds.Top+2, splitButton.DropDownButtonBounds.Right-3, buttonBounds.Bottom-3);

            e.Graphics.SetClip(buttonBounds, CombineMode.Exclude);
            this.RenderButtonInternal(e.Graphics, e.ToolStrip, new Rectangle(Point.Empty, e.Item.Size), splitButton.DropDownButtonSelected, splitButton.DropDownButtonPressed, splitButton.DropDownButtonPressed || splitButton.ButtonPressed);
            e.Graphics.ResetClip();

            this.RenderButtonInternal(e.Graphics, e.ToolStrip, buttonBounds, splitButton.ButtonSelected, false, splitButton.ButtonPressed);

            RenderArrowInternal(e.Graphics, arrowBounds, ArrowDirection.Down, splitButton.ForeColor);
        }

        // Ripped from ToolStripRenderer 
        protected override void OnRenderStatusStripSizingGrip(ToolStripRenderEventArgs e)
        {
            StatusStrip toolStrip = e.ToolStrip as StatusStrip;

            if (toolStrip != null)
            {
                Rectangle sizeGripBounds = toolStrip.SizeGripBounds;

                if (sizeGripBounds.Width > 0 && sizeGripBounds.Height > 0)
                {
                    Rectangle[] glyphLight = new Rectangle[baseSizeGripRectangles.Length];
                    Rectangle[] glyphDark = new Rectangle[baseSizeGripRectangles.Length];
                    for (int count = 0; count < baseSizeGripRectangles.Length; count++)
                    {
                        Rectangle glyph = baseSizeGripRectangles[count];
                        if (toolStrip.RightToLeft == RightToLeft.Yes)
                        {
                            glyph.X = (sizeGripBounds.Width - glyph.X) - glyph.Width;
                        }
                        glyph.Offset(sizeGripBounds.X, sizeGripBounds.Bottom - 12);
                        glyphLight[count] = glyph;
                        if (toolStrip.RightToLeft == RightToLeft.Yes)
                        {
                            glyph.Offset(1, -1);
                        }
                        else
                        {
                            glyph.Offset(-1, -1);
                        }
                        glyphDark[count] = glyph;
                    }
                    using (Brush lightBrush = new SolidBrush(Color.FromArgb(128, Color.White)), darkBrush = new SolidBrush(Color.FromArgb(128, Color.Black)))
                    {
                        e.Graphics.FillRectangles(lightBrush, glyphLight);
                        e.Graphics.FillRectangles(darkBrush, glyphDark);
                    }
                }
            }
        }

        [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
        protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
        {
            ToolStrip topStrip = TopMostToolStrip(e.ToolStrip);
            // There is currently a bug in ContextMenuStrip (which MS have been aware of since June 2007)
            // If you click on a ContextMenuItem that does not dismiss (i.e. it has child items) then the 
            // SourceControl property will be set to null. This is a problem here as ContextmenuStrip 
            // returns null for FindForm(), null for TopLevelControl and null for Parent.

            // Please vote for this bug to be fixed at the following link.
            // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=282496

            // Hopefully MS will fix this bug one day (instead of just telling us it's fixed) and this method 
            // will then work fine.
            Control sourceControl = topStrip is ContextMenuStrip ? ((ContextMenuStrip)topStrip).SourceControl : topStrip;
            GlassForm form = sourceControl == null ? null : sourceControl.FindForm() as GlassForm;
            Color brushColor = e.ToolStrip.BackColor;
            bool designMode = form == null ? GlassToolStripRenderer.DesignMode(e.ToolStrip) : GlassToolStripRenderer.DesignMode(form);

            bool onGlass = form == null ? false : form.ControlIsOnGlass(e.ToolStrip);

            bool glazedDropDowns = form == null ? false : form.GetGlazeDropDowns(topStrip);
            bool raisedToolStrip = form == null ? false : form.GetRaisedToolStrip(e.ToolStrip);
            bool defaultToGlass = form == null ? false : form.GetDefaultToGlass(e.ToolStrip);

            if (onGlass)
            {
                e.Graphics.Clear(Color.Transparent);
                if (defaultToGlass)
                    brushColor = Color.Empty;
            }
            else
            {
                if (e.ToolStrip.IsDropDown && GlassUtilities.GlassEnabled && !designMode)
                {
                    if ( topStrip != null)
                    {
                        if (glazedDropDowns)
                        {
                            NativeMethods.DWMAPI.MARGINS margins = new NativeMethods.DWMAPI.MARGINS(-1, 0, 0, 0);
                            NativeMethods.DWMAPI.DwmExtendFrameIntoClientArea(e.ToolStrip.Handle, ref margins);
                            e.Graphics.Clear(GlassUtilities.SystemGlassColor);
                            return;
                        }
                    }
                }
                else
                {
                    using (Brush brush = new SolidBrush(brushColor))
                        e.Graphics.FillRectangle(brush, e.ToolStrip.ClientRectangle);
                }
            }
            if (e.ToolStrip.IsDropDown)
            {
                e.Graphics.Clear(brushColor);
            }
            else
            {
                if (raisedToolStrip)
                {
                    e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
                    using (GraphicsPath path = GlassUtilities.RoundedRectangle(e.AffectedBounds, 4))
                    {
                        using (Brush brush = new SolidBrush(brushColor))
                            e.Graphics.FillPath(brush, path);
                        int gradientAngle = e.ToolStrip.Orientation == Orientation.Horizontal ? 90 : 0;
                        using (Brush brush = new LinearGradientBrush(e.AffectedBounds, Color.FromArgb(192, 255, 255, 255), Color.FromArgb(64, 0, 0, 0), gradientAngle))
                            e.Graphics.FillPath(brush, path);
                    }
                }
                else
                {
                    e.Graphics.Clear(brushColor);
                }
            }
        }

        protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
        {
            Rectangle rc = e.ToolStrip.ClientRectangle;
            if (e.ToolStrip.IsDropDown)
            {
                rc.Width--;
                rc.Height--;
                Color glass = GlassUtilities.SystemGlassColor;
                using (Pen pen = new Pen(Color.FromArgb(Math.Max(192, (int)glass.A), glass)))
                    e.Graphics.DrawRectangle(pen, rc);
            }
            else
            {
                ToolStrip topStrip = TopMostToolStrip(e.ToolStrip);
                GlassForm form = topStrip == null ? null : topStrip.FindForm() as GlassForm;

                bool raisedToolStrip = form == null ? false : form.GetRaisedToolStrip(e.ToolStrip);
                if (raisedToolStrip)
                {
                    Color brushColor = e.ToolStrip.BackColor;

                    Color glass = GlassUtilities.GlassEnabled ? GlassUtilities.SystemGlassColor : brushColor;

                    using (GraphicsPath path = GlassUtilities.RoundedRectangle(rc, 4))
                    {
                        using (Pen pen = new Pen(Color.FromArgb(Math.Max(192, (int)glass.A), glass)))
                        {
                            e.Graphics.DrawPath(pen, path);
                            rc.Inflate(-1, -1);
                            path.Reset();
                            path.AddPath(GlassUtilities.RoundedRectangle(rc, 3), false);
                            pen.Color = Color.FromArgb(192, Color.White);
                            e.Graphics.DrawPath(pen, path);
                        }
                    }
                }
            }
        }

        protected override void OnRenderToolStripContentPanelBackground(ToolStripContentPanelRenderEventArgs e)
        {
            GlassForm form = e.ToolStripContentPanel.FindForm() as GlassForm;
            bool onGlass = form == null ? false : form.ControlIsOnGlass(e.ToolStripContentPanel);
            Color brushColor = onGlass ? Color.Empty : e.ToolStripContentPanel.BackColor;
            using (Brush brush = new SolidBrush(brushColor))
                e.Graphics.FillRectangle(brush, e.ToolStripContentPanel.ClientRectangle);
            e.Handled = true;
        }

        protected override void OnRenderToolStripPanelBackground(ToolStripPanelRenderEventArgs e)
        {
            GlassForm form = e.ToolStripPanel.FindForm() as GlassForm;
            bool onGlass = form == null ? false : form.ControlIsOnGlass(e.ToolStripPanel);
            Color brushColor = onGlass ? Color.Empty : e.ToolStripPanel.BackColor;
            using (Brush brush = new SolidBrush(brushColor))
                e.Graphics.FillRectangle(brush, e.ToolStripPanel.ClientRectangle);
            e.Handled = true;
        }

        protected override void OnRenderToolStripStatusLabelBackground(ToolStripItemRenderEventArgs e)
        {
            GlassForm form = e.ToolStrip.FindForm() as GlassForm;
            bool onGlass = form == null ? false : form.ControlIsOnGlass(e.ToolStrip);
            if (!onGlass)
            {
                Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size);
                using (Brush brush = new SolidBrush(e.Item.BackColor))
                    e.Graphics.FillRectangle(brush, bounds);
            }
        }

        #endregion

        #region Custom Render Methods

        public void DrawTabBackground(ToolStripItemRenderEventArgs e)
        {
            OnRenderTabBackground(e);
        }

        protected virtual void OnRenderTabBackground(ToolStripItemRenderEventArgs e)
        {
            ToolStripTab item = e.Item as ToolStripTab;

            // Set up smooth drawing
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;

            ToolStrip topStrip = this.TopMostToolStrip(e.ToolStrip);
            GlassForm form = topStrip.FindForm() as GlassForm;

            Color glowColor = SystemColors.Highlight;
            Color startColor = Color.FromArgb(192, Color.White);
            Color endColor = item.BackColor;

            bool itemOnGlass = false;

            if (form != null)
            {
                glowColor = form.GetGlowColor(topStrip);
                if (glowColor.IsEmpty)
                    glowColor = form.GlowColor;
                itemOnGlass = form.ControlIsOnGlass(e.ToolStrip);
            }

            if (itemOnGlass)
                endColor = Color.Transparent;
                       
            if (item.Checked || item.Selected)
            {
                Rectangle rc = new Rectangle(Point.Empty, e.Item.Size);
                GraphicsPath path = TabPath(rc, 8, item.TabOrientation);

                // Fill with the Gradient
                float angle;

                switch (item.TabOrientation)
                {
                    case TabAlignment.Left:
                        angle = 0;
                        break;
                    case TabAlignment.Right:
                        angle = 180;
                        break;
                    case TabAlignment.Bottom:
                        angle = 270;
                        break;
                    default:
                        angle = 90;
                        break;
                }

                // Blend into Background
                if (itemOnGlass)
                    e.Graphics.CompositingMode = CompositingMode.SourceCopy;

                Rectangle brushBounds = rc;
                brushBounds.Height++;
                brushBounds.Width++;
                using (LinearGradientBrush brush = new LinearGradientBrush(brushBounds, startColor, endColor, angle))
                {
                    e.Graphics.FillPath(brush, path);
                }

                // Don't blend glow
                e.Graphics.CompositingMode = CompositingMode.SourceOver;

                // Draw a Glow
                if (!item.Checked)
                {
                    Rectangle bounds = rc;
                    bounds.Offset(0, bounds.Height / 2);

                    using (GraphicsPath glowPath = new GraphicsPath())
                    {
                        glowPath.AddEllipse(bounds);

                        using (PathGradientBrush brush = new PathGradientBrush(glowPath))
                        {
                            brush.CenterColor = glowColor;
                            brush.SurroundColors = new Color[] { Color.Transparent };
                            e.Graphics.SetClip(path, CombineMode.Replace);
                            e.Graphics.FillPath(brush, glowPath);
                            e.Graphics.ResetClip();
                        }
                    }
                }

                Color glass = topStrip.BackColor;

                if (GlassUtilities.GlassEnabled)
                    glass = GlassUtilities.SystemGlassColor;

                // Draw the border
                using (Pen pen = new Pen(Color.FromArgb(Math.Max(192, (int)glass.A), glass)))
                {
                    e.Graphics.DrawPath(pen, path);
                    switch (item.TabOrientation)
                    {
                        case TabAlignment.Bottom:
                            rc.Width -= 2;
                            rc.Height--;
                            rc.Offset(1, 0);
                            break;
                        case TabAlignment.Left:
                            rc.Width--;
                            rc.Height -= 2;
                            rc.Offset(1, 1);
                            break;
                        case TabAlignment.Right:
                            rc.Width--;
                            rc.Height -= 2;
                            rc.Offset(0, 1);
                            break;
                        default:
                            rc.Width -= 2;
                            rc.Height--;
                            rc.Offset(1, 1);
                            break;
                    }
                    //rc.Inflate(-1, -1);
                    path.Reset();
                    path.AddPath(TabPath(rc, 7, item.TabOrientation), false);
                    pen.Color = Color.FromArgb(192, Color.White);
                    e.Graphics.DrawPath(pen, path);
                }

                path.Dispose();
            }
        }

        #endregion

        #region Internal Helper Methods

        internal static bool DesignMode(Component component)
        {
            if (component.Site == null)
                return false;
            return component.Site.DesignMode;
        }

        internal ToolStrip TopMostToolStrip(ToolStrip toolStrip)
        {
            if (toolStrip.IsDropDown)
            {
                ToolStripItem ownerItem = ((ToolStripDropDown)toolStrip).OwnerItem;
                if (ownerItem != null)
                {
                    ToolStrip owner = ownerItem.Owner;
                    if (owner != null)
                    {
                        if (owner.IsDropDown)
                        {
                            return TopMostToolStrip((ToolStripDropDown)owner);
                        }
                        else
                        {
                            return owner;
                        }
                    }
                }
            }
            return toolStrip;
        }

        internal static GraphicsPath TabPath(Rectangle bounds, int radius, TabAlignment tabAlignment)
        {
            //Make sure the Path fits inside the rectangle
            bounds.Width--;
            bounds.Height--;

            //Scale the radius if it's too large to fit.
            if (radius > (bounds.Width))
                radius = bounds.Width;
            if (radius > (bounds.Height))
                radius = bounds.Height;

            System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
            
            switch (tabAlignment)
            {
                case TabAlignment.Left:
                    path.AddLine(bounds.Right, bounds.Bottom, bounds.Left + radius, bounds.Bottom);
                    path.AddArc(bounds.Left, bounds.Bottom - radius, radius, radius, 90, 90);
                    path.AddArc(bounds.Left, bounds.Top, radius, radius, 180, 90);
                    path.AddLine(bounds.Left + radius, bounds.Top, bounds.Right, bounds.Top);
                    break;

                case TabAlignment.Right:
                    path.AddLine(bounds.Left, bounds.Top, bounds.Right - radius, bounds.Top);
                    path.AddArc(bounds.Right - radius, bounds.Top, radius, radius, 270, 90);
                    path.AddArc(bounds.Right - radius, bounds.Bottom - radius, radius, radius, 0, 90);
                    path.AddLine(bounds.Right - radius, bounds.Bottom, bounds.Left, bounds.Bottom);
                    break;

                case TabAlignment.Bottom:
                    path.AddLine(bounds.Right, bounds.Top, bounds.Right, bounds.Bottom - radius);
                    path.AddArc(bounds.Right - radius, bounds.Bottom - radius, radius, radius, 0, 90);
                    path.AddArc(bounds.Left, bounds.Bottom - radius, radius, radius, 90, 90);
                    path.AddLine(bounds.Left, bounds.Bottom - radius, bounds.Left, bounds.Top);
                    break;

                default:
                    path.AddLine(bounds.Left, bounds.Bottom, bounds.Left, bounds.Top + radius);
                    path.AddArc(bounds.Left, bounds.Top, radius, radius, 180, 90);
                    path.AddArc(bounds.Right - radius, bounds.Top, radius, radius, 270, 90);
                    path.AddLine(bounds.Right, bounds.Top + radius, bounds.Right, bounds.Bottom); 
                    break;
            }

            return path;
        }

        #endregion

        internal void RenderButtonInternal(Graphics graphics, ToolStrip toolStrip, Rectangle itemBounds, bool selected, bool isChecked, bool pressed)
        {
            if (selected || isChecked)
            {
                // Set up smooth drawing
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.CompositingQuality = CompositingQuality.HighQuality;

                ToolStrip topStrip = this.TopMostToolStrip(toolStrip);
                GlassForm form = topStrip.FindForm() as GlassForm;

                Color glowColor = SystemColors.Highlight;

                if (form != null)
                {
                    glowColor = form.GetGlowColor(topStrip);
                    if (glowColor.IsEmpty)
                        glowColor = form.GlowColor;
                }

                Color topColor = Color.FromArgb(128, Color.White);
                Color bottomColor = Color.FromArgb(128, Color.Black);

                Rectangle rc = itemBounds;
                rc.Width--;
                rc.Height--;

                GraphicsPath path = GlassUtilities.RoundedRectangle(rc, 4);

                if (pressed || isChecked)
                {
                    // Set up the Gradient Color
                    topColor = glowColor;
                    bottomColor = glowColor;
                }

                // Fill with the Gradient
                using (LinearGradientBrush brush = new LinearGradientBrush(rc, Color.FromArgb(192, topColor), bottomColor, LinearGradientMode.Vertical))
                {
                    brush.WrapMode = WrapMode.TileFlipX;
                    graphics.FillPath(brush, path);
                }

                // Don't blend glow
                graphics.CompositingMode = CompositingMode.SourceOver;

                // Draw a Glow
                if (selected)
                {
                    Rectangle bounds = rc;
                    bounds.Offset(0, bounds.Height / 2);

                    using (GraphicsPath glowPath = new GraphicsPath())
                    {
                        glowPath.AddEllipse(bounds);

                        using (PathGradientBrush brush = new PathGradientBrush(glowPath))
                        {
                            brush.CenterColor = glowColor;
                            brush.SurroundColors = new Color[] { Color.Transparent };
                            Region clipRgn = graphics.Clip;
                            graphics.SetClip(path, CombineMode.Replace);
                            graphics.FillPath(brush, glowPath);
                            graphics.SetClip(clipRgn, CombineMode.Replace);
                        }
                    }
                }

                Color glass = topStrip.BackColor;

                if (GlassUtilities.GlassEnabled)
                    glass = GlassUtilities.SystemGlassColor;

                // Draw the border
                using (Pen pen = new Pen(Color.FromArgb(Math.Max(192, (int)glass.A), glass)))
                {
                    graphics.DrawPath(pen, path);
                    rc.Inflate(-1, -1);
                    path.Reset();
                    path.AddPath(GlassUtilities.RoundedRectangle(rc, 3), false);
                    pen.Color = Color.FromArgb(192, Color.White);
                    graphics.DrawPath(pen, path);
                }

                path.Dispose();
            }
        }

        internal static void RenderArrowInternal(Graphics g, Rectangle bounds, ArrowDirection direction, Color arrowColor)
        {
            CompositingQuality quality = g.CompositingQuality;
            SmoothingMode smooth = g.SmoothingMode;

            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;

            Point centerPoint = new Point(bounds.Left + (bounds.Width / 2), bounds.Top + (bounds.Height / 2));

            Point[] points = null;

            switch (direction)
            {
                case ArrowDirection.Left:
                    points = new Point[] { new Point(centerPoint.X + 2, centerPoint.Y - 3), new Point(centerPoint.X + 2, centerPoint.Y + 3), new Point(centerPoint.X - 2, centerPoint.Y) };
                    break;

                case ArrowDirection.Up:
                    points = new Point[] { new Point(centerPoint.X - 3, centerPoint.Y + 2), new Point(centerPoint.X + 3, centerPoint.Y + 2), new Point(centerPoint.X, centerPoint.Y - 2) };
                    break;

                case ArrowDirection.Right:
                    points = new Point[] { new Point(centerPoint.X - 2, centerPoint.Y - 3), new Point(centerPoint.X - 2, centerPoint.Y + 3), new Point(centerPoint.X + 2, centerPoint.Y) };
                    break;

                default:
                    points = new Point[] { new Point(centerPoint.X - 3, centerPoint.Y - 2), new Point(centerPoint.X + 3, centerPoint.Y - 2), new Point(centerPoint.X, centerPoint.Y + 2) };
                    break;
            }

            using (GraphicsPath path = new GraphicsPath())
            {
                path.AddEllipse(new Rectangle(centerPoint.X-6,centerPoint.Y-6,12,12));
                using (PathGradientBrush brush = new PathGradientBrush(path))
                {
                    brush.CenterColor = Color.FromArgb(96, Color.White);
                    brush.SurroundColors = new Color[] { Color.Transparent };
                    Blend blend = new Blend(2);
                    blend.Factors = new float[]{0,.2f,1};
                    blend.Positions = new float[]{0, .9f, 1};
                    brush.Blend = blend;
                    g.FillEllipse(brush, path.GetBounds());
                }
            }

            using (Brush brush = new SolidBrush(arrowColor))
                g.FillPolygon(brush, points);

            g.CompositingQuality = quality;
            g.SmoothingMode = smooth;
        }

    }
}
